// **************************************************************
// COPYRIGHT(c)2020, Xidian University
// All rights reserved.
//
// IP LIB INDEX :  
// IP Name      :      
// File name    :  
// Module name  :  
// Full name    :  
// Time         : 2021 
// Author       : Haoxiaofei 
// Email        : 1531804419@qq.com
// Data         : 
// Version      : V 1.0 
// 
// Abstract     :
// Called by    :  
// 
// Modification history
// -----------------------------------------------------------------
// 3\u548c4\u8868\u5408\u4e00\uff0c\u52a8\u4f5c\u4e09\u6682\u65f6\u4e0d\u8fde\u63a5\uff0c\u4e0b\u7248\u672c\u52a0\u6307\u4ee4\u5904\u7406\u518d\u6539\u56de\u6765
// 
//
// *****************************************************************

//*******************
//DEFINE MODULE PORT
//*******************
module ME3(
    input wire rst_n,
    input wire clk,
    input wire [11:0]ram_dp_cfg_register,

    //ME\u4e0eCPU\u63a5\u53e3

    input  wire[14:0]  ram_addr1,
    // input  wire[16:0]  ram_addr1,
    input  wire[31:0]  ram_data1,
    input  wire        cpu_wen1,
    input  wire        cpu_ren1,
    output wire[31:0]  read_data_cpu1,
    output wire        read_data_valid1,

    input  wire[14:0]  ram_addr2,
    // input  wire[16:0]  ram_addr2,
    input  wire[31:0]  ram_data2,
    input  wire        cpu_wen2,
    input  wire        cpu_ren2,
    output wire[31:0]  read_data_cpu2,
    output wire        read_data_valid2,

    // input  wire [15:0] me_array_action3_dpram_addr       ,
    // input  wire        me_array_action3_dpram_wen        ,
    // input  wire [31:0] me_array_action3_dpram_wdata      ,
    // input  wire        me_array_action3_dpram_ren        , 
    //\u5b57\u6bb5\u9009\u62e9\u63a5\u53e3
    input  wire [0:1023]pktheader_vector,
    input  wire [255:0]ctr_field,
    input  wire vector_rdy,//\u5b57\u6bb5\u9009\u62e9\u4f7f\u80fd

    input  wire lookup_done4,
    output reg  [31:0]  match_res_t3       
    ); 

//*******************
//DEFINE LOCAL PARAMETER
//*******************
//parameter(s)

//*********************
//INNER SIGNAL DECLARATION
//*********************
//REGS
reg [14:0]ram_addr;

reg lookup_done_ff;

reg lookup_done;
wire [31:0] match_res3_ff;

reg [95:0]rbve_data1;
reg [63:0]rbve_data2;
reg [95:0]rbve_data;
reg cpu_wen  ;
reg cpu_ren1_ff;
reg cpu_ren2_ff;
//WIRES
wire[31:0] match_res3;

wire lookup_done3;
//wire lookup_success3;

wire select_end_o;

//ME3
wire [255:0]rule_in3;

reg        cpu_wen1_ff;
reg [14:0] ram_addr1_ff;

reg        cpu_wen2_ff;
reg [14:0] ram_addr2_ff;
//*********************
//INSTANTCE MODULE
//*********************
//ME3
field_mux_256 U_3(
    .clk(clk),
    .rst_n(rst_n),
    .vector_rdy(vector_rdy),
    .ctr_field(ctr_field),
    .pktheader_vector(pktheader_vector),
    .select_end_o(select_end_o),
    .match_field(rule_in3)
    );

rbve_256 U_3_rbve(
    .clk(clk),
    .rst_n(rst_n),
    .ram_dp_cfg_register(ram_dp_cfg_register),
    .lookup_en(select_end_o),

    .ram_addr(ram_addr),
    .ram_data(rbve_data),
    .cpu_wen(cpu_wen),
    .cpu_ren1(cpu_ren1_ff),
    .read_data_cpu1(read_data_cpu1),
    .read_data_valid1(read_data_valid1),
    .cpu_ren2(cpu_ren2_ff),
    .read_data_cpu2(read_data_cpu2),
    .read_data_valid2(read_data_valid2),

    .range(rule_in3),
    //.match_is(lookup_success3),
    .match(match_res3),
    .lookup_done(lookup_done3)
    );

rbve_fifo U_rbve_fifo (
    .clock(clk),
    .rst_n(rst_n),
    .fifo_wen(lookup_done3),
    .fifo_wdata(match_res3),
    .fifo_ren(lookup_done4),
    .fifo_rdata(match_res3_ff),
    .fifo_empty_rd(),
    .almost_full()
);

// match2action_pkt_4 U_table3(
//     .clk(clk),
//     .rst_n(rst_n),

//     .match_en(lookup_done),
//     .match_res(match_res_t3),//match_res_t3

//     .action_o(action_o),
//     .action_en_o(action_en_o),

//     .cpu_wen(me_array_action3_dpram_wen),
//     .cpu_ren(me_array_action3_dpram_ren),
//     .ram_data(me_array_action3_dpram_wdata),
//     .ram_addr(me_array_action3_dpram_addr),
//     .read_data_cpu(me_array_action3_dpram_rdata)
//     );
//*********************
//MAIN CORE
//********************* 
always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
    lookup_done_ff  <= 0;
  else if(lookup_done4)
    lookup_done_ff  <= 1;
  else 
    lookup_done_ff  <= 0;
end

always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
    match_res_t3 <= 0;
  else if(lookup_done_ff)
    match_res_t3 <= match_res3_ff;
  else 
    match_res_t3 <= match_res_t3;
end

always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
    lookup_done <= 0;
  else 
    lookup_done <= lookup_done_ff;
end
//\u4e24\u4e2a\u63a7\u5236\u4f7f\u80fd\u4fe1\u53f7\u6682\u65f6\u4e0d\u9700\u8981\uff0c\u540e\u7eed\u5728\u8c03\u6574  HXF 2021\u30015\u30018
// assign ctr_en3 = (ram_addr[22]==1)?1'b1:1'b0;
// assign par_ctr_en3 = (ram_addr[28]==1)?1'b1:1'b0;
//\u7531\u4e8eCPU\u914d\u7f6e\u63a5\u53e3\u9488\u5bf9RBVE\u914d\u7f6e\u5b58\u5728\u4e24\u4e2aSLAVE,\u4e00\u4e2a\u9488\u5bf9\u7b2c\u4e00\u7ea796bit,\u53e6\u4e00\u4e2a\u9488\u5bf964bit\u89c4\u5219\u914d\u7f6e\u3002
always@(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0) begin
       rbve_data1        <= 0;
    end
    else if(cpu_wen1)begin
        case(ram_addr1[9:8])// 2022.5.9 xym
        // case(ram_addr1[15:14])
          2'b01:
            rbve_data1 <= {ram_data1,64'b0};
          2'b10:
            rbve_data1 <= {rbve_data1[95:64],ram_data1,32'b0};
          2'b11:
            rbve_data1 <= {rbve_data1[95:32],ram_data1};
          default: rbve_data1 <= 0;
        endcase // addra[6:5]
    end
end

always @(posedge clk or negedge rst_n) begin
  if(~rst_n) begin
    cpu_wen1_ff      <= 0;
    ram_addr1_ff     <= 0;
  end 
  else begin
    cpu_wen1_ff      <= cpu_wen1;
    ram_addr1_ff     <= ram_addr1;
  end
end

//32--->64
always@(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0) begin
       rbve_data2        <= 0;
    end
    else if(cpu_wen2)begin
        case(ram_addr2[9:8])// 2022.5.9 xym
        // case(ram_addr2[15:14])
          2'b01:
            rbve_data2 <= {ram_data2,32'b0};
          2'b10:
            rbve_data2 <= {rbve_data2[63:32],ram_data2};
          default: rbve_data2 <= 0;
        endcase // addra[6:5]    
    end
end

always @(posedge clk or negedge rst_n) begin
  if(~rst_n) begin
    cpu_wen2_ff      <= 0;
    ram_addr2_ff     <= 0;
  end 
  else begin
    cpu_wen2_ff      <= cpu_wen2;
    ram_addr2_ff     <= ram_addr2;
  end
end

//\u65f6\u5e8f\u540c\u6b65
always@(posedge clk or negedge rst_n)begin
  if(rst_n == 1'b0)begin
    cpu_wen       <= 1'b0;
    cpu_ren1_ff   <= 1'b0;
    cpu_ren2_ff   <= 1'b0;
    rbve_data     <= 96'b0;
    ram_addr      <= 15'b0;
  end
  else if (cpu_wen1_ff)begin//wirte 96 width_ram
    cpu_wen       <= 1'b1;
    cpu_ren1_ff   <= 1'b0;
    cpu_ren2_ff   <= 1'b0;
    rbve_data     <= rbve_data1;
    ram_addr      <= ram_addr1_ff;
  end
  else if (cpu_wen2_ff)begin//wirte 64 width_ram
    cpu_wen       <= 1'b1;
    cpu_ren1_ff   <= 1'b0;
    cpu_ren2_ff   <= 1'b0;
    rbve_data     <= {32'b0,rbve_data2};
    ram_addr      <= ram_addr2_ff;
  end
  else if (cpu_ren1)begin//rd 96 width_ram
    cpu_wen       <= 1'b0;
    cpu_ren1_ff   <= 1'b1;
    cpu_ren2_ff   <= 1'b0;
    rbve_data     <= 96'b0;
    ram_addr      <= ram_addr1;
  end
  else if (cpu_ren2)begin//rd 64 width_ram
    cpu_wen       <= 1'b0;
    cpu_ren1_ff   <= 1'b0;
    cpu_ren2_ff   <= 1'b1;
    rbve_data     <= 96'b0;
    ram_addr      <= ram_addr2;
  end
  else begin
    cpu_wen       <= 1'b0;
    cpu_ren1_ff   <= 1'b0;
    cpu_ren2_ff   <= 1'b0;
    rbve_data     <= rbve_data;
    ram_addr      <= ram_addr;
  end
end

//*********************
endmodule    // hookup byte controller block
